package com.bob.web.common.shiro;

import com.bob.web.common.constant.SystemHoldContext;
import com.bob.web.dao.AdminDao;
import com.bob.web.dao.RoleDao;
import com.bob.web.entity.system.Admin;
import com.bob.web.entity.system.Resource;
import com.bob.web.entity.system.Role;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 名称: MyShiroRealm<br>
 * 描述:<br>
 * 类型: JAVA<br>
 * 最近修改时间:2017/7/14 14:14<br>
 *
 * @author BoYangsh
 * @version [版本号, V1.0]
 * @since 2017/7/14 14:14
 */
public class MyShiroRealm extends AuthorizingRealm {

//	@Autowired
	private AdminDao adminDao;
//	@Autowired
	private RoleDao roleDao;


	//授权
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		//因为我用的是usernameAndPasswordToken，所以这里存储的就是用户名，本系统用户名唯一
		String username = (String) principals.getPrimaryPrincipal();
//		Admin admin = adminDao.findAdminByUsername(username, "username", "roles");
		Admin admin = new Admin();
		admin.setUsername("admin");
		admin.setPassword("admin");
		List<Role> roles = roleDao.findRole(admin.getRoleNames(), "resourceUris");
		//如果没有任何角色，则直接返回一个空的info
		if(CollectionUtils.isEmpty(roles)) {
			return info;
		}
		Set<String> resourceUris = new HashSet<>();
		roles.forEach(role -> {
			resourceUris.addAll(role.getResourceUris());
		});
		info.addRoles(admin.getRoleNames()); //添加角色
		info.addStringPermissions(resourceUris); //添加资源
		return info;
	}

	//认证
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
		String username = (String) token.getPrincipal();
		//这里根据传进来的用户名去查找用户名
		Admin admin = adminDao.findAdminByUsername(username);
		if(admin == null) {
			throw new UnknownAccountException("=============不存在用户:" + username); //抛出未找到对应账户的异常
		}
		//将用户名存储到本地线程
		SystemHoldContext.setCurrentUser(admin);
		//因为在凭证策略配置的时候，是用md5进行加密，所以这里因为从数据库拿到的密码并没有加密，为了防止校验的时候
		//失败，这里手动加密一下
		String password =  new SimpleHash("md5", admin.getPassword(), ByteSource.Util.bytes(
				username + "" + admin.getPassword()), 2).toHex();
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, // 用户名
				password, // 密码
				ByteSource.Util.bytes(username + "" + admin.getPassword()),// salt=username+salt
				getName()); // realm name
		return authenticationInfo;
	}
}
